module cfg_mstr(cmd_data, snd_frm, rsp, RX_C, TX_C, clk, rst_n, rsp_rdy);

input [23:0] cmd_data;
input snd_frm, clk, rst_n, RX_C;

output reg [15:0] rsp;
output reg rsp_rdy;
output TX_C;


typedef enum reg [1:0] { IDLE, LOAD, TRMT, RCV } state_t;

state_t state, nxt_state;

reg [1:0] byte_cnt;
reg [23:0] cmd;
reg [15:0] resp_data;

logic shift, clr_byte_cnt, u_clr_rdy, u_trmt, rd_cmd, set_resp, u_rdy, clr_resp_rdy;

wire [7:0] u_tx_data, u_rx_data;

assign u_tx_data = cmd[23:16];

UART uart (.clk(clk), .rst_n(rst_n), .TX(TX_C), .RX(RX_C), .tx_data(u_tx_data), 
		.trmt(u_trmt), .tx_done(u_tx_done), .rx_data(u_rx_data), .rdy(u_rdy), .clr_rdy(u_clr_rdy));



//state transfer logic
always_ff @(posedge clk, negedge rst_n) 
	begin
		if(!rst_n)
			state <= IDLE;
		else 
			state <= nxt_state;
	end


//if shifting, the byte count increases
//or resets if clr_byte_cnt
always_ff @(posedge clk, negedge rst_n) 
	begin
		if(!rst_n)
			byte_cnt <= 2'h0;
		else if(clr_byte_cnt)
			byte_cnt <= 2'h0;
		else if(shift)
			byte_cnt <= byte_cnt + 1;
	end



//shifting the cmd_data, to the next 8 bits
always_ff @(posedge clk, negedge rst_n) 
	begin
		if(!rst_n)
			cmd <= 24'h000;
		else if (rd_cmd)
			cmd <= cmd_data;
		else if (shift)
			cmd <= {cmd[15:0],8'hFF};
	end

//sets resp to data
always_ff @(posedge clk, negedge rst_n) 
	begin
		if(!rst_n)
			rsp <= 16'h0000;
		else if ( set_resp )
			rsp <= resp_data;
	end

always_ff @(posedge clk, negedge rst_n) 
	begin
		if(!rst_n)
			resp_data <= 16'h0000;
		else if( shift ) 
			resp_data <= {u_rx_data, resp_data[15:8]};
	end


//if set response, response ready is 1,
//if cleared or reset, 0
always_ff @(posedge clk, negedge rst_n)
	begin
		if(!rst_n)
			rsp_rdy <= 1'b0;
		else if(set_resp)
			rsp_rdy <= 1'b1;
		else if (clr_resp_rdy)
			rsp_rdy <= 1'b0;
	end



//state machine logic and control signals
always_comb 
	begin
		nxt_state = IDLE;
		shift = 0;
		clr_byte_cnt = 0;
		u_clr_rdy = 0;
		u_trmt = 0;
		rd_cmd = 0;
		set_resp = 0;
		clr_resp_rdy = 0;

		case(state)
		IDLE:
			begin
				if(snd_frm) begin
					rd_cmd = 1;
					nxt_state = LOAD;
				end
			end
		LOAD:
			begin
				nxt_state = TRMT;
				clr_byte_cnt = 1;
				u_trmt = 1;
				shift = 1;
			end
		TRMT:
			begin
				nxt_state = TRMT;
				if( byte_cnt == 2'h2 )
					begin
						clr_resp_rdy = 1;
						nxt_state = RCV;
						clr_byte_cnt = 1;
					end
				else if (u_tx_done)
					begin
						shift = 1;
						u_trmt = 1;
					end
			end
		RCV:
			begin
				nxt_state = RCV;
				if( byte_cnt == 2'h2)
					begin
						nxt_state = IDLE;
						set_resp = 1;
					end
				else if ( u_rdy )
					begin
						u_clr_rdy = 1;
						shift = 1;
					end
			end
		endcase;
	end

endmodule
